package com.ruoyi.web.service.incomeexpense.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.deepoove.poi.XWPFTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.utils.uuid.Seq;
import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.domain.category.Category;
import com.ruoyi.web.domain.category.Type;
import com.ruoyi.web.domain.incomeexpense.IncomeExpense;
import com.ruoyi.web.domain.incomeexpense.Proportion;
import com.ruoyi.web.domain.incomeexpense.ZQEmail;
import com.ruoyi.web.domain.park.Park;
import com.ruoyi.web.mapper.category.CategoryMapper;
import com.ruoyi.web.mapper.incomeexpense.IncomeExpenseMapper;
import com.ruoyi.web.pojo.dto.incomeexpense.IncomeExpenseDetailsVo;
import com.ruoyi.web.pojo.dto.incomeexpense.IncomeExpensePage;
import com.ruoyi.web.pojo.dto.incomeexpense.ProportionListVo;
import com.ruoyi.web.pojo.dto.incomeexpense.ProportionVo;
import com.ruoyi.web.pojo.request.incomeexpense.IEDetailsReq;
import com.ruoyi.web.pojo.request.incomeexpense.IEPageReq;
import com.ruoyi.web.service.category.ITypeService;
import com.ruoyi.web.service.incomeexpense.IIncomeExpenseService;
import com.ruoyi.web.service.incomeexpense.IZQEmailService;
import com.ruoyi.web.service.park.IParkService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.init.ResourceReader;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.activation.DataSource;
import javax.mail.internet.MimeMessage;
import javax.mail.util.ByteArrayDataSource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * 支入支出Service业务层处理
 *
 * @author zq
 * &#064;date  2024-01-09
 */
@Slf4j
@Service
public class IncomeExpenseService implements IIncomeExpenseService {
    private final IncomeExpenseMapper incomeExpenseMapper;
    private final ITypeService typeMapper;
    private final CategoryMapper categoryMapper;
    private final JavaMailSender javaMailSender;
    private final IZQEmailService emailService;
    private final IParkService parkService;
    private final ITypeService typeService;
    private static final String MONEY = "money";
    private static final String TITLE = "title";
    private final ISysUserService sysUserService;
    @Autowired
    private ServerConfig serverConfig;

    public IncomeExpenseService(IncomeExpenseMapper incomeExpenseMapper, ITypeService typeMapper, CategoryMapper categoryMapper, JavaMailSender javaMailSender, IZQEmailService emailService, IParkService parkService, ITypeService typeService, ISysUserService sysUserService) {
        this.incomeExpenseMapper = incomeExpenseMapper;
        this.typeMapper = typeMapper;
        this.categoryMapper = categoryMapper;
        this.javaMailSender = javaMailSender;
        this.emailService = emailService;
        this.parkService = parkService;
        this.typeService = typeService;
        this.sysUserService = sysUserService;
    }

    /**
     * 查询支入支出
     *
     * @param id 支入支出主键
     * @return 支入支出
     */
    @Override
    public IncomeExpensePage selectIncomeExpenseById(Long id) {
        IncomeExpense incomeExpense = incomeExpenseMapper.selectIncomeExpenseById(id);

        Type type = typeMapper.selectTypeById(incomeExpense.getTypeId());
        IncomeExpensePage page = new IncomeExpensePage(incomeExpense);
        page.setState(type.getState());
        page.setTypeName(type.getTypeName());
        if (Boolean.TRUE.equals(type.getHasLevel())) {
            Category category = categoryMapper.selectCategoryById(incomeExpense.getChildId());
            page.setChildName(category.getName());
        } else {
            page.setChildName(incomeExpense.getChildId());
        }
        SysUser sysUser = sysUserService.selectUserById(incomeExpense.getUserId());
        if (Objects.nonNull(sysUser)) {
            page.setAccount(sysUser.getUserName());
            page.setUserName(sysUser.getNickName());
        }
        return page;
    }

    /**
     * 查询支入支出列表
     *
     * @param req 支入支出
     * @return 支入支出
     */
    @Override
    public List<IncomeExpensePage> selectIncomeExpenseList(IEPageReq req) {
        boolean isAdmin = SecurityUtils.isParkManager();
        req.setUserId(isAdmin ? null : SecurityUtils.getUserId());
        if (Objects.isNull(req.getTypeIds()) || req.getTypeIds().length == 0) {
            throw new ServiceException("未选一级分类");
        }
        boolean isStartTimePresent = Objects.nonNull(req.getStartTime());
        boolean isEndTimePresent = Objects.nonNull(req.getEndTime());
        if (isStartTimePresent && isEndTimePresent) {
            req.setStartTime(DateUtils.minDate(req.getStartTime()));
            req.setEndTime(DateUtils.maxDate(req.getEndTime()));
        }

        List<IncomeExpensePage> incomeExpenses = incomeExpenseMapper.selectIncomeExpenseListVo(req);

        incomeExpenses.forEach(s -> {
            Type type = typeMapper.selectTypeById(s.getTypeId());
            List<Category> categoryList = type.getCategoryList();
            s.setTypeName(type.getTypeName());
            s.setState(type.getState());
            if (Boolean.TRUE.equals(type.getHasLevel())) {
                Optional<Category> first = categoryList.stream().filter(c -> c.getId().equals(s.getChildId())).findFirst();
                first.ifPresent(category -> s.setChildName(category.getName()));
            } else {
                if (CollectionUtils.isEmpty(categoryList)) {
                    switch (s.getChildId()) {
                        case "0":
                            s.setSource("中央补贴");
                            break;
                        case "1":
                            s.setSource("省级补贴");
                            break;
                        case "2":
                            s.setSource("市级补贴");
                            break;
                        case "3":
                            s.setSource("县级补贴");
                            break;
                        case "4":
                            s.setSource("乡镇级补贴");
                            break;
                        default:
                            s.setSource(null);
                            break;
                    }
                    s.setChildId(null);
                } else {
                    boolean parallel = categoryList.stream().filter(c -> c.getId().equals(s.getChildId())).isParallel();
                    if (parallel) {
                        s.setChildName(categoryList.stream().filter(c -> c.getId().equals(s.getChildId())).findFirst().get().getName());
                    }
                }
            }
        });
        return incomeExpenses;
    }

    /**
     * 新增支入支出
     *
     * @param incomeExpense 支入支出
     * @return 结果
     */
    @Override
    public int insertIncomeExpense(IncomeExpense incomeExpense) {
        //查询分类
        getType(incomeExpense);

        incomeExpense.setCreateTime(DateUtils.getNowDate());
        incomeExpense.setCreateBy(SecurityUtils.getUsername());
        incomeExpense.setUpdateTime(DateUtils.getNowDate());
        incomeExpense.setUpdateBy(SecurityUtils.getUsername());
        incomeExpense.setUserId(SecurityUtils.getUserId());
        return incomeExpenseMapper.insertIncomeExpense(incomeExpense);
    }

    private void getType(IncomeExpense incomeExpense) {
        if (Objects.isNull(incomeExpense.getTypeId())) {
            throw new UtilException("请输入分类");
        }
        Type type = typeMapper.selectTypeById(incomeExpense.getTypeId());
        if (Objects.isNull(type)) {
            throw new UtilException("分类不存在");
        }
    }

    /**
     * 修改支入支出
     *
     * @param incomeExpense 支入支出
     * @return 结果
     */
    @Override
    public int updateIncomeExpense(IncomeExpense incomeExpense) {
        //查询分类
        getType(incomeExpense);

        IncomeExpense incomeExpense1 = incomeExpenseMapper.selectIncomeExpenseById(incomeExpense.getId());
        incomeExpense.setUpdateTime(DateUtils.getNowDate());
        incomeExpense.setUpdateBy(SecurityUtils.getUsername());
        if (SecurityUtils.isParkManager() || SecurityUtils.getUserId().equals(incomeExpense1.getUserId())) {
            incomeExpense.setUserId(incomeExpense1.getUserId());
        } else {
            throw new ServiceException("没有权限");
        }
        return incomeExpenseMapper.updateIncomeExpense(incomeExpense);
    }

    /**
     * 批量删除支入支出
     *
     * @param ids 需要删除的支入支出主键
     * @return 结果
     */
    @Override
    public int deleteIncomeExpenseByIds(Long[] ids) {
        return incomeExpenseMapper.deleteIncomeExpenseByIds(ids);
    }

    /**
     * 删除支入支出信息
     *
     * @param id 支入支出主键
     * @return 结果
     */
    @Override
    public int deleteIncomeExpenseById(Long id) {
        IncomeExpense incomeExpense1 = incomeExpenseMapper.selectIncomeExpenseById(id);
        if (SecurityUtils.isParkManager() || SecurityUtils.getUserId().equals(incomeExpense1.getUserId())) {
            return incomeExpenseMapper.deleteIncomeExpenseById(id);
        } else {
            throw new ServiceException("没有权限");
        }
    }

    @Override
    public ProportionListVo selectDetailsListVo(IEDetailsReq req) {
        IEPageReq req1 = new IEPageReq();
        req1.setUserId(SecurityUtils.getUserId());
        req1.setName(req.getName());
        req1.setStartMoney(req.getStartMoney());
        req1.setEndMoney(req.getEndMoney());
        if (Objects.nonNull(req.getStartTime()) && Objects.nonNull(req.getEndTime())) {
            req1.setStartTime(DateUtils.minDate(req.getStartTime()));
            req1.setEndTime(DateUtils.maxDate(req.getEndTime()));
        }

        //进行一级分类查询
        Type type = new Type();
        type.setUserId(SecurityUtils.getUserId());
        type.setType(req.getType());
        List<Type> types;
        if (Objects.nonNull(req.getTypeId())) {
            types = new ArrayList<>();
            type.setId(req.getTypeId());
            Type typeById = typeMapper.selectTypeById(req.getTypeId());
            types.add(typeById);
        } else {
            types = typeMapper.selectTypeList(type);
        }

        String[] array = types.stream().map(Type::getId).toArray(String[]::new);
        req1.setTypeIds(array);
        //查询出所有数据
        List<IncomeExpenseDetailsVo> incomeExpenses = incomeExpenseMapper.selectDetailsList(req1);
        ProportionListVo listVo = new ProportionListVo();
        List<ProportionVo> typeList = new ArrayList<>();
        if (Objects.nonNull(req.getTypeId())) {
            if (Boolean.TRUE.equals(types.get(0).getHasLevel())) {
                List<Category> categoryList = types.get(0).getCategoryList();
                if (CollectionUtils.isNotEmpty(categoryList)) {
                    incomeExpenses.stream()
                            .collect(Collectors.groupingBy(IncomeExpenseDetailsVo::getChildId))
                            .forEach((key, value) -> {
                                ProportionVo proportion = new ProportionVo();
                                AtomicReference<BigDecimal> income = new AtomicReference<>(BigDecimal.ZERO);
                                Optional<Category> first = categoryList.stream()
                                        .filter(category -> category.getId().equals(key))
                                        .findFirst();
                                if (first.isPresent()) {
                                    Category categoryVo = first.get();
                                    value.forEach(s -> {
                                        s.setChildName(categoryVo.getName());
                                        income.set(income.get().add(s.getMoney()));
                                    });
                                    proportion.setName(categoryVo.getName());
                                }
                                proportion.setId(key);
                                proportion.setValue(income.get().toString());
                                typeList.add(proportion);
                            });
                }

            } else {
                ProportionVo proportion = new ProportionVo();
                proportion.setName(types.get(0).getTypeName());
                proportion.setId(types.get(0).getId());
                AtomicReference<BigDecimal> income = new AtomicReference<>(BigDecimal.ZERO);
                for (IncomeExpenseDetailsVo vo : incomeExpenses) {
                    income.set(income.get().add(vo.getMoney()));
                }
                proportion.setValue(income.get().toString());
                typeList.add(proportion);
            }

        }
        else {
            incomeExpenses.stream().collect(Collectors.groupingBy(IncomeExpenseDetailsVo::getTypeId))
                    .forEach((k, v) -> {
                        Optional<Type> first = types.stream().filter(s -> s.getId().equals(k)).findFirst();
                        ProportionVo proportion = new ProportionVo();
                        AtomicReference<BigDecimal> income = new AtomicReference<>(BigDecimal.ZERO);
                        if (first.isPresent()) {
                            Type typeVo = first.get();
                            proportion.setId(typeVo.getId());
                            proportion.setName(typeVo.getTypeName());
                            //没二级
                            if (Boolean.FALSE.equals(typeVo.getHasLevel())) {
                                v.forEach(q -> {
                                    q.setTypeName(typeVo.getTypeName());
                                    income.set(income.get().add(q.getMoney()));
                                });
                                proportion.setValue(income.get().toString());
                            } else {
                                proportion.setId(typeVo.getId());
                                proportion.setName(typeVo.getTypeName());
                                List<Category> categoryList = typeVo.getCategoryList();
                                if (CollectionUtils.isNotEmpty(categoryList)) {
                                    List<IncomeExpenseDetailsVo> inList = new ArrayList<>();
                                    for (Category category : categoryList) {
                                        List<IncomeExpenseDetailsVo> collect = v.stream()
                                                .filter(s -> s.getChildId().equals(category.getId()))
                                                .peek(q -> q.setChildName(category.getName()))
                                                .peek(q -> income.set(income.get().add(q.getMoney())))
                                                .peek(q -> q.setTypeName(typeVo.getTypeName()))
                                                .collect(Collectors.toList());
                                        inList.addAll(collect);
                                    }
                                    proportion.setValue(income.get().toString());
                                    //排序
                                    inList.sort(Comparator.comparing(IncomeExpenseDetailsVo::getCreateTime).reversed());
                                }
                            }

                        }
                        typeList.add(proportion);
                    });
        }
        listVo.setList(incomeExpenses);//.stream().limit(10).collect(Collectors.toList())
        listVo.setTypeList(typeList);
        if (CollectionUtil.isEmpty(listVo.getList())){
            listVo.setTypeList(new ArrayList<>());
        }
        return listVo;
    }

    @Override
    public List<Proportion> selectDetailsList(IEDetailsReq req) {
        IEPageReq req1 = new IEPageReq();
        req1.setUserId(SecurityUtils.getUserId());
        req1.setName(req.getName());
        req1.setStartMoney(req.getStartMoney());
        req1.setEndMoney(req.getEndMoney());

        Optional.ofNullable(req.getStartTime()).ifPresent(startTime -> req1.setStartTime(DateUtils.minDate(startTime)));
        Optional.ofNullable(req.getEndTime()).ifPresent(endTime -> req1.setEndTime(DateUtils.maxDate(endTime)));

        Type type = new Type();
        type.setUserId(SecurityUtils.getUserId());
        type.setType(req.getType());

        List<Type> types;
        if (Objects.nonNull(req.getTypeId())) {
            types = Collections.singletonList(typeMapper.selectTypeById(req.getTypeId()));
        } else {
            types = typeMapper.selectTypeList(type);
        }

        String[] array = types.stream().map(Type::getId).toArray(String[]::new);
        req1.setTypeIds(array);
        //查询出所有数据
        List<IncomeExpenseDetailsVo> incomeExpenses = incomeExpenseMapper.selectDetailsList(req1);
        List<Proportion> proportions = new ArrayList<>();

        if (Objects.nonNull(req.getTypeId())) {
            if (Boolean.TRUE.equals(types.get(0).getHasLevel())) {
                List<Category> categoryList = types.get(0).getCategoryList();
                incomeExpenses.stream()
                        .collect(Collectors.groupingBy(IncomeExpenseDetailsVo::getChildId))
                        .forEach((key, value) -> {
                            Proportion proportion = new Proportion();
                            Optional<Category> first = categoryList.stream()
                                    .filter(category -> category.getId().equals(key)).findFirst();
                            if (first.isPresent()) {
                                Category categoryFilter = first.get();
                                proportion.setName(categoryFilter.getName());
                                proportion.setId(key);
                                proportion.setList(value);
                                proportion.setValue(value.size());
                                proportions.add(proportion);
                            }
                        });
            } else {
                Proportion proportion = new Proportion();
                proportion.setName(types.get(0).getTypeName());
                proportion.setId(types.get(0).getId());
                proportion.setList(incomeExpenses);
                proportion.setValue(incomeExpenses.size());
                proportions.add(proportion);
            }

        } else {
            incomeExpenses.stream()
                    .collect(Collectors.groupingBy(IncomeExpenseDetailsVo::getTypeId))
                    .forEach((k, v) -> {
                        Optional<Type> first = types.stream()
                                .filter(s -> s.getId().equals(k)).findFirst();
                        Proportion proportion = new Proportion();
                        if (first.isPresent()) {
                            Type type1 = first.get();
                            proportion.setId(type1.getId());
                            proportion.setName(type1.getTypeName());
                            //没二级
                            if (Boolean.FALSE.equals(type1.getHasLevel())) {
                                List<IncomeExpenseDetailsVo> collect = v.stream()
                                        .peek(q -> q.setTypeName(type1.getTypeName()))
                                        .collect(Collectors.toList());
                                proportion.setList(collect);
                                proportion.setValue(collect.size());
                            } else {
                                List<Category> categoryList = type1.getCategoryList();

                                if (CollectionUtils.isNotEmpty(categoryList)) {
                                    List<IncomeExpenseDetailsVo> inList = new ArrayList<>();
                                    int value = 0;
                                    for (Category category : categoryList) {
                                        List<IncomeExpenseDetailsVo> collect = v.stream()
                                                .filter(s -> s.getChildId().equals(category.getId()))
                                                .peek(q -> {
                                                    q.setChildName(category.getName());
                                                    q.setTypeName(type1.getTypeName());
                                                }).collect(Collectors.toList());
                                        value += collect.size();
                                        inList.addAll(collect);
                                    }
                                    proportion.setValue(value);
                                    //排序
                                    inList.sort(Comparator.comparing(IncomeExpenseDetailsVo::getCreateTime).reversed());
                                    proportion.setList(inList);
                                }
                            }
                        }
                        proportions.add(proportion);
                    });
        }
        return proportions;
    }

    @Override
    public Map<String, Object> countIncomeExpenseMoney() {
        Map<String, Object> map = new HashMap<>();
        Result typeResult = getResult();
        BigDecimal income = incomeExpenseMapper.countIncomeExpenseMoney(typeResult.incomeType, SecurityUtils.getUserId());
        BigDecimal expense = incomeExpenseMapper.countIncomeExpenseMoney(typeResult.expenseType, SecurityUtils.getUserId());
        map.put("income", income);
        map.put("expense", expense);
        if (Objects.isNull(income)) {
            income = new BigDecimal(0);
        }
        BigDecimal result = Optional.of(income)
                .map(v1 -> expense != null ? v1.subtract(expense) : // 如果value2不为null，则进行减法操作
                        v1.subtract(BigDecimal.ZERO)) // 如果value2为null，则使用默认的减法运算（减零）
                .orElse(null); // value1为null时的默认值
        map.put(MONEY, result);
        return map;
    }

    @Override
    public long count(IEPageReq req) {
        return incomeExpenseMapper.count(req);
    }

    @Override
    public String export(IEDetailsReq req, HttpServletResponse response) throws Exception {
        String username = SecurityUtils.getUsername();
        Park park = parkService.getUserId(SecurityUtils.getUserId());
        List<Proportion> list = this.selectDetailsList(req);
        ObjectMapper objectMapper = new ObjectMapper();
        ZQEmail email = new ZQEmail();
        email.setEmail(req.getEmail());
        email.setUserId(SecurityUtils.getUserId());
        email.setEmail(req.getEmail());
        email.setSubstance(objectMapper.writeValueAsString(list));
        email.setUpdateTime(DateUtils.getNowDate());
        emailService.insertZQEmail(email);
        BigDecimal money = new BigDecimal("0");
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (Proportion s : list) {
            Map<String, Object> re = new HashMap<>();
            re.put("name", s.getName());
            BigDecimal reduce = s.getList().stream().map(IncomeExpenseDetailsVo::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            re.put(MONEY, reduce);
            List<Map<String, Object>> collect = s.getList().stream().map(v -> {
                Map<String, Object> vo = new HashMap<>();
                vo.put("recordDate", DateUtils.formatDate(v.getRecordDate()));
                vo.put("name", Objects.nonNull(v.getName()) ? v.getName() : v.getInsuranceCompany() + ":" + v.getInsurance());
                vo.put(MONEY, v.getMoney());
                return vo;
            }).collect(Collectors.toList());
            re.put("lists", collect);
            money = money.add(reduce);
            mapList.add(re);
        }
        String title;
        if (StringUtils.isNull(req.getType())) {
            title = "总利润";
        } else {
            title = "0".equals(req.getType()) ? "收入" : "支出";
        }
        Map<String, Object> map = new HashMap<>();
        map.put(TITLE, title);
        map.put("username", username);
        if (Objects.nonNull(park)) {
            map.put("address", park.getFullAddress());
        }
        if (Objects.nonNull(req.getStartTime()) && Objects.nonNull(req.getEndTime())) {
            map.put("startEndTime", DateUtils.formatDate(req.getStartTime()) + "至" + DateUtils.formatDate(req.getEndTime()));
        }
        map.put(MONEY, money);
        map.put("Time", DateUtils.formatChinese(new Date()));
        map.put("list", mapList);

       return createPdf(map);
    }

    @Override
    public String export(IEDetailsReq req) {
        IEPageReq pageReq = req.toPoVo();
        if (StringUtils.isEmpty(req.getTypeId()) && StringUtils.isNotEmpty(req.getType())){
            Type type = new Type();
            type.setType(req.getType());
            List<Type> types = this.typeService.selectTypeList(type);
            if (CollectionUtil.isNotEmpty(types)){
                String[] array = types.stream().map(Type::getId).toArray(String[]::new);
                pageReq.setTypeIds(array);
            }
        }
        List<IncomeExpensePage> pageList = this.selectIncomeExpenseList(pageReq);
        ExcelUtil<IncomeExpensePage> util = new ExcelUtil<>(IncomeExpensePage.class);
        util.init(pageList,"收支数据","收支数据", Excel.Type.EXPORT);

        String name = StringUtils.generateRandomString(16);
        String fileName = StringUtils.format("{}/{}.{}", DateUtils.datePath(),
                name, "xlsx");
        try{
            String absolutePath = FileUploadUtils.getAbsoluteFile(FileUploadUtils.getDefaultBaseDir(), fileName).getAbsolutePath();
            util.exportExcel(absolutePath);
        }catch (Exception e){
            log.error("生成Excel文件失败");
            e.printStackTrace();
        }
        String outputFilePath = "/profile/"+fileName;
       return serverConfig.getUrl() + outputFilePath;
    }

    @Override
    public Map<String, Object> profit(IEDetailsReq req) {
        String username = SecurityUtils.getUsername();
        Park park = parkService.getUserId(SecurityUtils.getUserId());
        List<Proportion> list = this.selectDetailsList(req);
        //zq-》分出支入支出
        List<Type> types = typeService.selectTypeList(new Type());
        List<String> incomeType = types.stream().filter(type -> "0".equals(type.getType())).map(Type::getId).collect(Collectors.toList());
        List<String> expenseType = types.stream().filter(type -> "1".equals(type.getType())).map(Type::getId).collect(Collectors.toList());
        final BigDecimal[] income = {new BigDecimal(0)};
        final BigDecimal[] expense = {new BigDecimal(0)};
        //已有分类匹配
        List<Proportion> incomeCollect = list.stream().filter(type -> incomeType.stream().anyMatch(t -> t.equals(type.getId()))).collect(Collectors.toList());
        List<Proportion> expenseCollect = list.stream().filter(type -> expenseType.stream().anyMatch(t -> t.equals(type.getId()))).collect(Collectors.toList());
        List<IncomeExpenseDetailsVo> incomeList = new ArrayList<>();
        List<IncomeExpenseDetailsVo> expenseList = new ArrayList<>();
        incomeCollect.forEach(s -> {
            incomeList.addAll(s.getList());
            s.getList().forEach(v -> income[0] = income[0].add(v.getMoney()));
        });
        expenseCollect.forEach(s -> {
            expenseList.addAll(s.getList());
            s.getList().forEach(v -> expense[0] = expense[0].add(v.getMoney()));
        });

        Map<String, Object> map = new HashMap<>();
        map.put("incomeList", incomeList);
        map.put("expenseList", expenseList);

        String title = StringUtils.isNull(req.getType()) ? "总利润" : ("0".equals(req.getType()) ? "收入" : "支出");
        map.put(TITLE, title);
        map.put("username", username);

        if (park != null) {
            map.put("address", park.getFullAddress());
        }

        if (req.getStartTime() != null && req.getEndTime() != null) {
            map.put("startEndTime", DateUtils.formatDate(req.getStartTime()) + "至" + DateUtils.formatDate(req.getEndTime()));
        }

        BigDecimal profit = income[0].subtract(expense[0]);
        map.put(MONEY, profit);
        map.put("income", income[0]);
        map.put("expense", expense[0]);
        map.put("Time", DateUtils.formatChinese(new Date()));
        return map;
    }

    private Result getResult() {
        List<Type> types = getAllTypeList();
        List<String> incomeType = types.stream().filter(type -> "0".equals(type.getType())).map(Type::getId).collect(Collectors.toList());
        List<String> expenseType = types.stream().filter(type -> "1".equals(type.getType())).map(Type::getId).collect(Collectors.toList());
        return new Result(incomeType, expenseType);
    }

    private static class Result {
        public final List<String> incomeType;
        public final List<String> expenseType;

        public Result(List<String> incomeType, List<String> expenseType) {
            this.incomeType = incomeType;
            this.expenseType = expenseType;
        }
    }

    private List<Type> getAllTypeList() {
        return typeService.selectTypeList(new Type());
    }

    //生成doc文件并通过邮件方式发送给指定人
    private void seedEmail(Map<String, Object> map, String email, HttpServletResponse response, String title) {
        try {
            //获取模板
            InputStream resourceAsStream = ResourceReader.class.getClassLoader().getResourceAsStream("template/title.docx");

            XWPFTemplate template;
            if (resourceAsStream != null) {
                template = XWPFTemplate.compile(resourceAsStream).render(map);
            } else {
                return;
            }
            //输出文件
            String fileName = title + "查询明细(总表).docx"; // 这应该是您希望用户下载的文件的真实名称和扩展名
            String fileName1 = title + "查询明细(总表)"; // 这应该是您希望用户下载的文件的真实名称和扩展名
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("\\+", "%20"); // 对文件名进行URL编码，并将空格由加号转为空格的百分编码
            response.reset();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ";filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8"));

            // 创建一个字节流
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            template.write(byteArrayOutputStream);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            // 创建一个MimeMessage对象
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);

            // 设置邮件相关信息
            helper.setFrom("wuxinxin0604@163.com"); // 发件人邮箱
            helper.setTo(email); // 收件人邮箱
            helper.setSubject(fileName1); // 邮件标题
            helper.setText("欢迎使用天府农创园，附件是您下载得报表。"); // 邮件内容
            DataSource dataSource = new ByteArrayDataSource(byteArrayInputStream, "application/octet-stream");

            helper.addAttachment(fileName, dataSource);

            // 发送邮件
            javaMailSender.send(message);
            byteArrayOutputStream.close();
            template.close();
        } catch (Exception e) {
            throw new ServiceException("发送邮箱失败");
        }
    }

    //生成PDF文件 返回路径
    private String createPdf(Map<String,Object> map){
        String outPath="";
        // 加载Word文档
        InputStream resourceAsStream = ResourceReader.class.getClassLoader().getResourceAsStream("template/title.docx");
        XWPFTemplate template ;
        if (resourceAsStream != null) {
            template = XWPFTemplate.compile(resourceAsStream).render(map);
            try{
                //将XWPFDocument转换为InputStream
                ByteArrayOutputStream b = new ByteArrayOutputStream();
                //这里的document=XWPFDocument document，在下面的word转换中
                template.write(b);
                String name = StringUtils.generateRandomString(16);
                String fileName = StringUtils.format("{}/{}.{}", DateUtils.datePath(),
                        name, "pdf");
                String absolutePath = FileUploadUtils.getAbsoluteFile(FileUploadUtils.getDefaultBaseDir(), fileName).getAbsolutePath();

                String wordName = StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
                        FilenameUtils.getBaseName(IdUtils.randomUUID()), Seq.getId(Seq.uploadSeqType), "doc");

                File wordPath = FileUploadUtils.getAbsoluteFile(FileUploadUtils.getDefaultBaseDir(), wordName);

                template.writeToFile(wordPath.getCanonicalPath());

//               // 实例化Document类的对象
//                Document doc = new Document();
//                //加载Word
//                doc.loadFromFile(wordPath.getCanonicalPath());
//                log.info("支入支出生成Word文件路径："+wordPath.getCanonicalPath());
//                log.info("支入支出生成PDF文件路径："+absolutePath);
//               // 保存为PDF格式
//                doc.saveToFile(absolutePath, FileFormat.PDF);
//                log.info("支入支出生成PDF转换成功");
//                doc.close();
               // wordToPdf(wordPath.getCanonicalPath(),absolutePath);
                //convertDocxToPdf(wordPath,absolutePath);
                boolean delete = wordPath.delete();
                String outputFilePath = "/profile/"+fileName;
                outPath = serverConfig.getUrl() + outputFilePath;
                log.info("支入支出生成PDF转换成功+++++");
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return outPath;
    }

}
